#include <memory>
#include <iostream>
#include <brpc/server.h>
#include <butil/logging.h>

// common文件夹下
#include "asrer.hpp"
#include "etcder.hpp"
#include "logger.hpp"
#include "speech.pb.h"

namespace bite_im
{
    // 实现语音识别功能

    // 语音识别服务类
    class SpeechServiceImpl : public bite_im::SpeechService
    {
    public:
        using ptr = std::shared_ptr<SpeechServiceImpl>;
        SpeechServiceImpl(const AsrClient::ptr &asr_client) : _asr_client(asr_client) {}
        ~SpeechServiceImpl() {}
        void SpeechRecognition(google::protobuf::RpcController *controller,
                               const ::bite_im::SpeechRecognitionReq *request,
                               ::bite_im::SpeechRecognitionRsp *response,
                               ::google::protobuf::Closure *done)
        {
            // 管理rpc对象
            brpc::ClosureGuard rpc_guard(done);
            // 1.获取请求中的语音数据
            // std::string content = request->speech_content();
            std::string err_msg;
            std::string ret = _asr_client->recognize(request->speech_content(), err_msg);
            if (ret.empty() == true)
            {
                LOG_ERROR("[{}]语音识别失败，原因[{}]", request->request_id(), err_msg);
                // 设置响应
                response->set_request_id(request->request_id());
                response->set_success(false);
                response->set_errmsg("语音识别失败，原因[" + err_msg + "]");
                return;
            }
            response->set_request_id(request->request_id());
            response->set_success(true);
            response->set_recognition_result(ret);
        }

    private:
        AsrClient::ptr _asr_client;
    };

    class SpeechServer
    {
        using RpcServerPtr = std::shared_ptr<brpc::Server>;

    public:
        using ptr = std::shared_ptr<SpeechServer>;
        SpeechServer(const AsrClient::ptr &asr_client,
                     const Registry::ptr &reg_client,
                     const RpcServerPtr &rpc_server)
            : _asr_client(asr_client), _reg_client(reg_client), _rpc_server(rpc_server)
        {
        }
        ~SpeechServer() {}

        // 启动RPC服务器
        void start()
        {
            _rpc_server->RunUntilAskedToQuit();
        }

    private:
        AsrClient::ptr _asr_client;
        Registry::ptr _reg_client;
        RpcServerPtr _rpc_server;
    };

    /*建造者设计模式，封装对象的构造过程，防止用户在进行操作时，对未构造的对象进行操作*/

    class SpeechServerBuilder
    {
        using RpcServerPtr = std::shared_ptr<brpc::Server>;

    public:
        // 构造语音识别客户端对象
        void make_asr_object(const std::string &app_id,
                             const std::string &api_key_id,
                             const std::string &api_key_secret)
        {
            _asr_client = std::make_shared<AsrClient>(app_id, api_key_id, api_key_secret);
        }
        // 构造服务注册客户端对象
        void make_reg_object(const std::string &reg_host,
                             const std::string &service_name,
                             const std::string &access_host)
        {
            _reg_client = std::make_shared<Registry>(reg_host);
            _reg_client->registry(service_name, access_host);
        }
        // 搭建rpc服务器
        void make_rpc_server(uint16_t port, int32_t time_out, uint8_t num_threads)
        {
            if (_asr_client.get() == nullptr)
            {
                LOG_ERROR("服务器建造失败，未初始化语音识别模块");
                abort();
            }
            // 创建rpc服务器对象
            _rpc_server = std::make_shared<brpc::Server>();
            // 构建服务，并添加服务
            SpeechServiceImpl *speech_service = new SpeechServiceImpl(_asr_client); // 注意这里需要在堆上开辟空间
            int ret = _rpc_server->AddService(speech_service, brpc::ServiceOwnership::SERVER_OWNS_SERVICE);
            if (ret == -1)
            {
                LOG_ERROR("rpc服务器添加服务失败");
                abort();
            }

            auto options = std::make_shared<brpc::ServerOptions>();
            // 启动服务器
            options->idle_timeout_sec = time_out; // 连接空闲超时时间
            options->num_threads = num_threads;
            ret = _rpc_server->Start(port, options.get());
            if (ret == -1)
            {
                LOG_ERROR("服务器启动失败");
                abort();
            }
        }
        SpeechServer::ptr build()
        {
            if (_reg_client.get() == nullptr)
            {
                LOG_ERROR("服务器建造失败，未初始化服务注册模块");
                abort();
            }
            if (_rpc_server.get() == nullptr)
            {
                LOG_ERROR("服务器建造失败，未搭建Rpc服务器");
                abort();
            }
            SpeechServer::ptr server = std::make_shared<SpeechServer>(_asr_client, _reg_client, _rpc_server);
            return server;
        }

    private:
        AsrClient::ptr _asr_client;
        Registry::ptr _reg_client;
        RpcServerPtr _rpc_server;
    };
}